package com.zmn.oms.admin.controller;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.channel.common.dro.ChannelDRO;
import com.zmn.base.channel.common.dro.ChannelSimpleDRO;
import com.zmn.base.channel.common.enums.ChannelTypeEnum;
import com.zmn.base.channel.common.query.ChannelQuery;
import com.zmn.base.channel.common.query.orderconfig.ChannelCombinationQuery;
import com.zmn.base.channel.dubbo.interfaces.channel.ChannelListRemoteService;
import com.zmn.base.channel.dubbo.interfaces.channel.relation.RelationRemoteService;
import com.zmn.base.common.data.common.dio.company.CompanyDIO;
import com.zmn.base.common.data.common.dio.company.CompanyTypeDIO;
import com.zmn.base.common.data.common.dro.area.AreaDRO;
import com.zmn.base.common.data.common.dro.brand.BrandDRO;
import com.zmn.base.common.data.common.dro.company.CompanyDRO;
import com.zmn.base.common.data.dubbo.interfaces.area.AreaListRemoteService;
import com.zmn.base.common.data.dubbo.interfaces.brand.BrandListRemoteService;
import com.zmn.base.common.data.dubbo.interfaces.company.CompanyListRemoteService;
import com.zmn.base.common.data.dubbo.interfaces.marketing.shop.MarketingShopListRemoteService;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.base.plat.engine.common.constant.CompanyConsts;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.base.product.common.dto.categ.CategProductDRO;
import com.zmn.base.product.common.dto.categ.CategServDRO;
import com.zmn.base.product.common.dto.categ.CategServProductDRO;
import com.zmn.base.product.common.dto.categ.ServCategDRO;
import com.zmn.base.product.common.dto.product.ProductBaseQuery;
import com.zmn.base.product.common.dto.product.ec.DefaultEcProductQuery;
import com.zmn.base.product.common.dto.product.ec.ProductBaseDRO;
import com.zmn.base.product.common.dto.product.erp.FaultWarrantyDRO;
import com.zmn.base.product.common.query.categ.CategProductQuery;
import com.zmn.base.product.common.query.categ.ForeignCategServProductQuery;
import com.zmn.base.product.common.query.categ.ForeignCategServQuery;
import com.zmn.base.product.dubbo.interfaces.categ.CategProductListRemoteService;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategServListRemoteService;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategServProductListRemoteService;
import com.zmn.base.product.dubbo.interfaces.channel.area.ChannelAreaCategListRemoteService;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductForeignListRemoteService;
import com.zmn.base.product.dubbo.interfaces.product.foreign.ProductTagsGroupForeignListRemoteService;
import com.zmn.common.dictionary.DictModel;
import com.zmn.common.dto.VtDTO;
import com.zmn.common.dto2.AMISListData;
import com.zmn.common.dto2.Option;
import com.zmn.common.dto2.OptionData;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.consts.GlobalConsts;
import com.zmn.mcc.cas.model.LoginStaff;
import com.zmn.mcc.cas.web.AbstractAdminController;
import com.zmn.mcc.common.constant.DpermitConsts;
import com.zmn.mcc.common.dto.organize.OrganizeDRO;
import com.zmn.mcc.common.dto.permit.SpermitDTO;
import com.zmn.mcc.dubbo.interfaces.organize.OrganizeListRemoteService;
import com.zmn.mcc.dubbo.interfaces.staff.StaffPermitRemoteService;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.conf.channel.ConfOrderChannelBService;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.vo.KVDict;
import com.zmn.oms.model.bo.product.ProductBO;
import com.zmn.oms.model.dto.common.ChannelListQuery;
import com.zmn.oms.model.dto.product.ProductQueryDTO;
import com.zmn.oms.model.dto.product.ShowProductDTO;
import com.zmn.oms.model.entity.conf.reply.ReplyCategory;
import com.zmn.oms.model.entity.conf.reply.ReplyCategoryQuery;
import com.zmn.oms.services.interfaces.conf.reply.ReplyCategoryService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkUploadService;
import com.zmn.saas.dubbo.dto.shop.ShopDRO;
import com.zmn.saas.dubbo.dto.shop.ShopTypeDIO;
import com.zmn.saas.dubbo.interfaces.shop.ShopRemoteService;
import com.zmn.scm2.common.model.dro.wms.goods.category.WmsGoodsCategoryDRO;
import com.zmn.scm2.common.model.query.wms.goods.category.GoodsCategoryShoppingQuery;
import com.zmn.scm2.dubbo.interfaces.wms.goods.category.GoodsCategoryListRemoteService;
import com.zmn.sp.common.enums.available.AvailableAreaLevelEnum;
import com.zmn.sp.dubbo.interfaces.available.AvailableAreaListRemoteService;
import com.zmn.sp.dubbo.interfaces.manage.SpManageListRemoteService;
import com.zmn.sp.dubbo.interfaces.rule.ServiceRuleListRemoteService;
import com.zmn.tapi.common.expressage.ExpressageCompany;
import com.zmn.tapi.dubbo.interfaces.expressage.ExpressageRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.elasticsearch.common.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：
 *
 * @author lujia
 * @date 2018/11/07 9:47
 */
public class OmsBaseController extends AbstractAdminController {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ChannelListRemoteService channelListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected CategServListRemoteService categServListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected BrandListRemoteService brandListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ProductForeignListRemoteService productForeignListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    protected ProductTagsGroupForeignListRemoteService productTagsGroupForeignListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected CategServProductListRemoteService categServProductListRemoteService;
    @DubboReference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    protected OrganizeListRemoteService organizeListRemoteService;
    @DubboReference(version = com.zmn.mcc.dubbo.dto.DubboConsts.INTERFACE_VERSION, check = false)
    protected StaffPermitRemoteService staffPermitRemoteService;
    @DubboReference(version = com.zmn.sp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    protected SpManageListRemoteService spManageListRemoteService;
    @DubboReference(version = com.zmn.saas.dubbo.constant.SaasDubboConsts.INTERFACE_VERSION, check = false)
    private ShopRemoteService shopRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected CompanyListRemoteService companyListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected CategProductListRemoteService categProductListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected AreaListRemoteService areaListRemoteService;
    @DubboReference(version = com.zmn.sp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    protected ServiceRuleListRemoteService serviceRuleListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected ChannelAreaCategListRemoteService channelAreaCategListRemoteService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    protected EngineerListRemoteService engineerListRemoteService;
    @Reference(version = com.zmn.sp.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    protected AvailableAreaListRemoteService availableAreaListRemoteService;
    @DubboReference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    protected GoodsCategoryListRemoteService goodsCategoryListRemoteService;
    @DubboReference(version = com.zmn.tapi.dubbo.DubboConsts.INTERFACE_VERSION, check = false)
    protected ExpressageRemoteService expressageRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected RelationRemoteService relationRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    protected MarketingShopListRemoteService marketingShopListRemoteService;


    @Resource
    private OrderWorkUploadService orderWorkUploadService;
    @Resource
    protected BaseCodeService baseCodeService;
    @Resource
    protected ConfOrderChannelBService confOrderChannelBService;
    @Resource
    protected ReplyCategoryService replyCategoryService;

    /**
     * 获取配件一级分类列表
     */
    protected List<KVDict> categOnelist() {
        GoodsCategoryShoppingQuery goodsCategoryShoppingQuery = new GoodsCategoryShoppingQuery();
        goodsCategoryShoppingQuery.setLevel(GlobalConsts.NO);
        goodsCategoryShoppingQuery.setStatus(GlobalConsts.YES);
        ResponseDTO<List<WmsGoodsCategoryDRO>> responseDTO = goodsCategoryListRemoteService
                .listCategory(goodsCategoryShoppingQuery);
        if (!responseDTO.isSuccess()) {
            logger.error("dubbo interface fail!");
            ResultDTO.success(Lists.newArrayList());
        }

        List<KVDict> list = responseDTO.getData().stream().map(e -> KVDict.builder().value(e.getCategId()).text(e.getCategName()).build()).collect(Collectors.toList());
        return list;
    }

    /**
     * 获取平台公司 （子公司）
     *
     * @return
     */
    protected List<KVDict> getCompanyListByDept(Integer plat) {
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(getCurrentStaff(), DpermitConsts.TYPE_ORGANIZE_SUB, false);
        if (CollectionUtils.isEmpty(spermitDTO.getItems())) {
            // 没有权限，如果是总部返回全部公司
            if(!this.isBranchCompany()){
                CompanyDIO baseCompanyDIO = new CompanyDIO();
                baseCompanyDIO.setType(CompanyConsts.COMPANY_TYPE_SUBSIDIARY);
                baseCompanyDIO.setChildType(CompanyConsts.COMPANY_TYPE_CHILD_DEFAULT);
                baseCompanyDIO.setPlat(plat);
                ResponseDTO<AMISListData<CompanyDRO>> responseDTO = companyListRemoteService.listPageCompanyDROByQuery(baseCompanyDIO);
                if(Objects.nonNull(responseDTO.getData()) && CollectionUtils.isNotEmpty(responseDTO.getData().getItems())){
                    return responseDTO.getData().getItems().stream().map(obj -> KVDict.builder().value(obj.getCompanyId()).text(obj.getName()).build()).collect(Collectors.toList());
                }
            }

            return Lists.newArrayList();
        }

        // 查询公司ID
        ResponseDTO<List<OrganizeDRO>> orgListResponseDTO = organizeListRemoteService.listByOrgIds(spermitDTO.getItems(), GlobalConsts.YES);
        if(CollectionUtils.isEmpty(orgListResponseDTO.getData())){
            return Lists.newArrayList();
        }

        List<Integer> orgIdList = orgListResponseDTO.getData().stream().map(OrganizeDRO::getCompanyId).collect(Collectors.toList());
        ResponseDTO<List<CompanyDRO>> responseDTO = companyListRemoteService.listByCompanyIds(orgIdList);
        if (CollectionUtils.isEmpty(responseDTO.getData())) {
            return Lists.newArrayList();
        }

        List<KVDict> list = Lists.newArrayListWithExpectedSize(responseDTO.getData().size());
        responseDTO.getData().forEach(e -> {
            if (Objects.nonNull(plat)) {
                if (Objects.equals(plat, e.getPlat())) {
                    list.add(KVDict.builder().value(e.getCompanyId()).text(e.getName()).build());
                }
            } else {
                list.add(KVDict.builder().value(e.getCompanyId()).text(e.getName()).build());
            }
        });
        return list;
    }

    /**
     * 获取服务公司
     *
     * @return
     */
    protected List<KVDict> getManageCompanyListByDept(Integer plat) {
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(getCurrentStaff(), DpermitConsts.TYPE_ORGANIZE_SP, false);
        if (CollectionUtils.isEmpty(spermitDTO.getItems())) {

            // 没有权限，如果是总部返回全部公司
            if(!this.isBranchCompany()){
                // 服务商 - 直营
                CompanyTypeDIO companyTypeDIO1 = new CompanyTypeDIO();
                companyTypeDIO1.setType(CompanyConsts.COMPANY_TYPE_SERVICE);
                companyTypeDIO1.setChildType(CompanyConsts.COMPANY_TYPE_SERVICE_OCO);

                // 服务商 - 非直营
                CompanyTypeDIO companyTypeDIO2 = new CompanyTypeDIO();
                companyTypeDIO2.setType(CompanyConsts.COMPANY_TYPE_SERVICE);
                companyTypeDIO2.setChildType(CompanyConsts.COMPANY_TYPE_SERVICE_NOT_OCO);

                CompanyDIO baseCompanyDIO = new CompanyDIO();
                baseCompanyDIO.setPlat(plat);
                baseCompanyDIO.setCompanyTypeQueryList(Arrays.asList(companyTypeDIO1, companyTypeDIO2));

                ResponseDTO<AMISListData<CompanyDRO>> responseDTO = companyListRemoteService.listPageCompanyDROByQuery(baseCompanyDIO);
                if (Objects.nonNull(responseDTO.getData()) && CollectionUtils.isNotEmpty(responseDTO.getData().getItems())) {
                    return responseDTO.getData().getItems().stream().map(obj -> KVDict.builder().value(obj.getCompanyId()).text(obj.getName()).build()).collect(Collectors.toList());
                }
            }

            return Lists.newArrayList();
        }

        ResponseDTO<List<CompanyDRO>> responseDTO = companyListRemoteService.listByCompanyIds(spermitDTO.getItems());
        if (CollectionUtils.isEmpty(responseDTO.getData())) {
            return Lists.newArrayList();
        }
        List<KVDict> list = Lists.newArrayListWithExpectedSize(responseDTO.getData().size());
        responseDTO.getData().forEach(e -> {
            if (Objects.nonNull(plat)) {
                if (Objects.equals(plat, e.getPlat())) {
                    list.add(KVDict.builder().value(e.getCompanyId()).text(e.getName()).build());
                }
            } else {
                list.add(KVDict.builder().value(e.getCompanyId()).text(e.getName()).build());
            }
        });
        return list;
    }


    /**
     * 获取前台产品一级分类
     * @param show 1 后台产品 2 前台产品
     * @return
     */
    protected List<KVDict> getOneCategoryListByShow(Integer show) {
        List<KVDict> kvDictList = Lists.newArrayList();
        CategProductQuery categoryDIO = new CategProductQuery();
        categoryDIO.setLevel(GlobalConsts.LEVEL_1);
        categoryDIO.setShowType(show);
        ResponseDTO<List<CategProductDRO>> responseDTO = categProductListRemoteService.listByQuery(categoryDIO);
        if (CollectionUtils.isNotEmpty(responseDTO.getData())) {
            responseDTO.getData().forEach(item -> {
                kvDictList.add(KVDict.<Integer>builder()
                        .value(item.getCategId())
                        .text(item.getCategName())
                        .build());
            });
        }
        return kvDictList;
    }


    /**
     * 获取产品一级分类
     * @param servCategId 服务分类
     * @param showType 产品类型 1 后端产品，2 前端产品
     * @return
     */
    protected List<KVDict> getOneCategoryList(Integer servCategId, Integer showType) {
        if (NumberUtil.isNullOrZero(servCategId)) {
            return Lists.newArrayList();
        }

        List<KVDict> kvDictList = Lists.newArrayList();
        logger.debug("获取一级分类入参 servCategId:{}, showType:{}", servCategId, showType);
        ResponseDTO<List<ServCategDRO>> responseDTO = categProductListRemoteService.listCategoryByServCategId(Lists.newArrayList(servCategId), showType);
        logger.debug("获取一级分类出参 {}}", JSON.toJSONString(responseDTO));
        if (responseDTO.isSuccess() && CollectionUtils.isNotEmpty(responseDTO.getData())) {
            List<ServCategDRO> items = responseDTO.getData();
            items.forEach(item -> {
                        kvDictList.add(KVDict.<Integer>builder()
                                .value(item.getCategOneId())
                                .text(item.getCategOneName())
                                .disabled(false)
                                .type(item.getCategOneId())
                                .pid(GlobalConsts.TOP_ID)
                                .build());
                    }
            );
        }
        return kvDictList;
    }

    /**
     * 获取产品二级分类
     * @param show 1 后台产品 2 前台产品
     * @return
     */
    protected List<KVDict> getTwoCategoryListByShow(Integer show) {
        List<KVDict> kvDictList = Lists.newArrayList();
        CategProductQuery categoryDIO = new CategProductQuery();
        categoryDIO.setLevel(GlobalConsts.LEVEL_2);
        categoryDIO.setShowType(show);
        ResponseDTO<List<CategProductDRO>> responseDTO = categProductListRemoteService.listByQuery(categoryDIO);
        if (responseDTO.isSuccess() && CollectionUtils.isNotEmpty(responseDTO.getData())) {
            List<CategProductDRO> items = responseDTO.getData();
            items.forEach(item -> {
                kvDictList.add(KVDict.<Integer>builder()
                        .value(item.getCategId())
                        .text(item.getCategName())
                        .build());
            });
        }
        return kvDictList;
    }

    /**
     * 获取产品二级分类
     * @param servCategId 服务分类
     * @param productShowType 产品类型 1 后端产品，2 前端产品
     * @return
     */
    protected List<KVDict> getTwoCategoryList(Integer servCategId, Integer productShowType) {
        if (NumberUtil.isNullOrZero(servCategId)) {
            return Lists.newArrayList();
        }

        List<KVDict> kvDictList = Lists.newArrayList();
        ForeignCategServProductQuery query = new ForeignCategServProductQuery();
        query.setShowType(productShowType);
        query.setServCategId(servCategId);
        ResponseDTO<AMISListData<CategServProductDRO>> responseDTO = categServProductListRemoteService.listPageCategGroupByServCategIdAndCategOneId(query);
        if (responseDTO.isSuccess() && Objects.nonNull(responseDTO.getData()) && CollectionUtils.isNotEmpty(responseDTO.getData().getItems())) {
            List<CategServProductDRO> items = responseDTO.getData().getItems();
            items.forEach(item -> {
                        kvDictList.add(KVDict.<Integer>builder()
                                .value(item.getCategId())
                                .text(item.getCategName())
                                .disabled(false)
                                .type(item.getCategOneId())
                                .pid(item.getServCategId())
                                .build());
                    }
            );
        }
        return kvDictList;
    }

    /**
     * 获取产品二级分类
     *
     * @param servCategId    服务分类
     * @param categOneIdList 一级产品list
     * @return
     */
    protected List<KVDict> getTwoCategoryList(Integer servCategId, List<Integer> categOneIdList, Integer showType) {
        List<KVDict> kvDictList = Lists.newArrayList();
        ForeignCategServProductQuery query = new ForeignCategServProductQuery();
        query.setServCategId(servCategId);
        query.setCategOneIds(categOneIdList);
        query.setShowType(showType);
        ResponseDTO<List<CategServProductDRO>> responseDTO = categServProductListRemoteService.listByQuery(query);
        if (responseDTO.isSuccess() && CollectionUtils.isNotEmpty(responseDTO.getData())) {
            List<CategServProductDRO> items = responseDTO.getData();
            items.forEach(item -> {
                kvDictList.add(KVDict.<Integer>builder()
                        .value(item.getCategId())
                        .text(item.getCategName())
                        .disabled(false)
//                        .pid(item.getParentId())
                        .build());
            });

        }
        return kvDictList;
    }

    /**
     * 获取产品二级分类
     *
     * @param categOneIdList 一级产品list
     * @return
     */
    protected List<KVDict> getTwoCategoryList(List<Integer> categOneIdList, Integer showType) {
        List<KVDict> kvDictList = Lists.newArrayList();
        ResponseDTO<OptionData<Integer>> responseDTO = categProductListRemoteService.listOptionByParentId(categOneIdList, showType, null);
        if (Objects.isNull(responseDTO.getData()) || CollectionUtils.isEmpty(responseDTO.getData().getOptions())) {
            return kvDictList;
        }
        List<Option<Integer>> items = responseDTO.getData().getOptions();
        items.forEach(item -> {
            kvDictList.add(KVDict.<Integer>builder()
                    .value(item.getValue())
                    .text(item.getLabel())
                    .disabled(item.getDisabled() == null ? true : item.getDisabled())
                    .build());
        });
        return kvDictList;
    }

    protected List<KVDict> areaDRO2KVDictList(ResponseDTO<List<AreaDRO>> areaResponse){
        List<AreaDRO> areaDROList = areaResponse.getData();
        if (CollectionUtils.isEmpty(areaDROList)) {
            return Lists.newArrayList();
        }

        List<KVDict> areaList = Lists.newArrayListWithCapacity(areaDROList.size());
        areaDROList.forEach(areaDRO -> {
            areaList.add(KVDict.<Integer>builder()
                    .value(areaDRO.getAreaId())
                    .text(areaDRO.getName())
                    .pid(areaDRO.getParentId())
                    .pidText(areaDRO.getProvinceName())
                    .disabled(Objects.equals(GlobalConsts.NO, areaDRO.getStatus()))
                    .build());
        });
        return areaList;
    }

    /**
     * 获取全部省份
     *
     * @return
     */
    protected List<KVDict> getAllProvinceList() {
        return this.getAreaListByPid(GlobalConsts.TOP_ID);
    }

    /**
     * 获取全部城市
     *
     * @return
     */
    protected List<KVDict> getAllCityList() {
        ResponseDTO<List<AreaDRO>> areaResponse = areaListRemoteService.listAllCity();
        return areaDRO2KVDictList(areaResponse);
    }

    /**
     * 获取父ID下的区域列表
     *
     * @return
     */
    protected List<KVDict> getAreaListByPid(Integer parentId) {
        if (NumberUtil.isNullOrZero(parentId)) {
            return Lists.newArrayList();
        }

        ResponseDTO<List<AreaDRO>> areaResponse = areaListRemoteService.listAreaByParentId(NumberUtil.isNullOrZero(parentId) ? GlobalConsts.TOP_ID : parentId);
        return areaDRO2KVDictList(areaResponse);
    }

    /**
     * 模糊查询城市
     *
     * @return
     */
    protected List<KVDict> fuzzyGetArea(String keyWord, Integer level, Integer parentId) {
        ResponseDTO<List<AreaDRO>> areaResponse = areaListRemoteService.getAreaByName(keyWord);
        areaResponse.getData().removeIf(areaDRO -> {
            if (parentId != null) {
                return !Objects.equals(areaDRO.getLevel(), level) || !Objects.equals(parentId, areaDRO.getParentId());
            } else {
                return !Objects.equals(areaDRO.getLevel(), level);
            }
        });
        return areaDRO2KVDictList(areaResponse);
    }

    /**
     * 获取父ID下的区域列表
     *
     * @return
     */
    protected List<KVDict> getCityListByPidAndDept(Integer parentId) {
        if (NumberUtil.isNullOrZero(parentId)) {
            return Lists.newArrayList();
        }

        ResponseDTO<List<AreaDRO>> areaResponse = areaListRemoteService.listAreaByParentId(parentId);
        logger.info("查询城市列表出参：【{}】", JSON.toJSONString(areaResponse));
        if (CollectionUtils.isEmpty(areaResponse.getData())) {
            return Lists.newArrayList();
        }

        // 获取城市权限
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(this.getLoginStaff(), DpermitConsts.TYPE_AREA_CITY, false);
        logger.info("查询城市权限出参：【{}】", JSON.toJSONString(spermitDTO));
        if (CollectionUtils.isEmpty(spermitDTO.getItems())) {
            return areaDRO2KVDictList(areaResponse);
        }

        List<KVDict> areaList = Lists.newArrayListWithCapacity(areaResponse.getData().size());
        Set<Integer> collect = spermitDTO.getItems().stream().collect(Collectors.toSet());
        areaResponse.getData().forEach(areaDRO -> {
            if (collect.contains(areaDRO.getAreaId())) {
                areaList.add(KVDict.<Integer>builder()
                        .value(areaDRO.getAreaId())
                        .text(areaDRO.getName())
                        .pid(areaDRO.getParentId())
                        .pidText(areaDRO.getProvinceName())
                        .build());
            }
        });
        return areaList;
    }

    /**
     * 获取省份
     *
     * @return
     */
    protected List<KVDict> getProvinceListByDept() {
        // 获取城市权限
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(this.getLoginStaff(), DpermitConsts.TYPE_AREA_PROVINCE, false);
        List<Integer> provinceList = spermitDTO.getItems();
        if (CollectionUtils.isEmpty(provinceList)) {
            // 没有权限，返回全部省份
            return this.getAllProvinceList();
        }
        List<KVDict> arrayList = new ArrayList<>(provinceList.size());
        List<List<Integer>> partitionList = Lists.partition(provinceList, 300);
        for (List<Integer> list : partitionList) {
            ResponseDTO<List<AreaDRO>> listResponseDTO = areaListRemoteService.listAreaByIds(list);
            arrayList.addAll(areaDRO2KVDictList(listResponseDTO));
        }
        return arrayList;
    }

    /**
     * 获取城市
     *
     * @return
     */
    protected List<KVDict> getCityListByDept() {
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(this.getLoginStaff(), DpermitConsts.TYPE_AREA_CITY, false);
        List<Integer> cityList = spermitDTO.getItems();
        if (CollectionUtils.isEmpty(cityList)) {
            // 没有权限，返回全部城市
            return this.getAllCityList();
        }

        List<KVDict> arrayList = new ArrayList<>(cityList.size());
        List<List<Integer>> partitionList = Lists.partition(cityList, 300);
        for (List<Integer> list : partitionList) {
            ResponseDTO<List<AreaDRO>> listResponseDTO = areaListRemoteService.listAreaByIds(list);
            arrayList.addAll(areaDRO2KVDictList(listResponseDTO));
        }
        return arrayList;
    }

    /**
     * 获取区域
     *
     * @param cityIdList
     * @return
     */
    protected List<KVDict> getCountListByCityIdsDept(Integer[] cityIdList) {
        ResponseDTO<List<VtDTO>> responseDTO = areaListRemoteService.listOptionCountryByCityIds(new ArrayList(Arrays.asList(cityIdList)));
        if (CollectionUtils.isEmpty(responseDTO.getData())) {
            return Lists.newArrayList();
        }

        // 获取权限
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(this.getCurrentStaff(), DpermitConsts.TYPE_AREA_COUNTY, false);
        if (CollectionUtils.isEmpty(spermitDTO.getItems())) {
            List<KVDict> vtList = Lists.newArrayListWithExpectedSize(responseDTO.getData().size());
            responseDTO.getData().forEach((item) -> {
                vtList.add(KVDict.builder().value(item.getValue()).text(item.getText()).build());
            });
            return vtList;
        }

        Set<Integer> collect = spermitDTO.getItems().stream().collect(Collectors.toSet());
        List<KVDict> vtList = Lists.newArrayListWithExpectedSize(collect.size());
        responseDTO.getData().forEach((item) -> {
            if (collect.contains(item.getValue())) {
                vtList.add(KVDict.<Integer>builder()
                        .value(item.getValue())
                        .text(item.getText())
                        .build());
            }
        });

        return vtList;
    }

    /**
     * 获取父ID下的区域详细信息列表
     *
     * @return
     */
    protected List<AreaDRO> getAreaDetailListByPid(Integer parentId) {
        if (NumberUtil.isNullOrZero(parentId)) {
            return Lists.newArrayList();
        }

        ResponseDTO<List<AreaDRO>> areaResponse = areaListRemoteService.listAreaByParentId(parentId);
        if (areaResponse.isSuccess() && CollectionUtils.isNotEmpty(areaResponse.getData())) {
            return areaResponse.getData();
        }
        return Lists.newArrayList();
    }

    protected AreaDRO getAreaDetailByCountyId(Integer countyId){
        if (NumberUtil.isNullOrZero(countyId)) {
            return null;
        }
        ResponseDTO<AreaDRO> areaDROResponseDTO = areaListRemoteService.getById(countyId);
        if (areaDROResponseDTO.isSuccess() && Objects.nonNull(areaDROResponseDTO.getData())) {
            return areaDROResponseDTO.getData();
        }

        return null;
    }

    /**
     * 获取可以服务的区域
     *
     * @param manageCompanyId
     * @param cityId
     * @return
     */
    protected List<KVDict> getPointAreaSupport(Integer manageCompanyId, Integer cityId) {
        if (NumberUtil.isNullOrZero(manageCompanyId)) {
            return Lists.newArrayList();
        }

        ResponseDTO<List<VtDTO>> responseDTO = availableAreaListRemoteService.listAvailableAreaBySpIdLimitParentArea(manageCompanyId,
                AvailableAreaLevelEnum.CITY, cityId, AvailableAreaLevelEnum.COUNTY);
        return this.vt2VKDict(responseDTO.getData());
    }

    /**
     * 获取区县
     *
     * @param cityId
     * @return
     */
    protected List<KVDict> getCountyList(Integer cityId) {
        ResponseDTO<OptionData<Integer>> listResponseDTO = areaListRemoteService.listOptionAreaByParentIdsAndLevel(Lists.newArrayList(cityId), null);
        return this.optionData2VKDict(listResponseDTO.getData());
    }

    /**
     * 获取渠道列表
     *
     * @return
     */
    protected List<KVDict> getChannelListByDept(Integer plat) {
        ChannelListQuery channelListQuery = ChannelListQuery.builder().plat(plat).
                excludeDisabledOrderInput(true).
                excludeDisabled(true).
                isPermit(true).
                factoryChannel(false).build();
        return this.getChannelList(channelListQuery);
    }

    /**
     * 获取渠道列表
     *
     * @param channelListQuery
     * @return
     */
    protected List<KVDict> getChannelList(ChannelListQuery channelListQuery) {

        ChannelCombinationQuery channelQuery = ChannelCombinationQuery
                .builder()
                .build();
        channelQuery.setPlat(channelListQuery.getPlat());
        channelQuery.setLikeName(channelListQuery.getKeyword());
        channelQuery.setRank(GlobalConsts.LEVEL_2);
        channelQuery.setContractModel(channelListQuery.getBizModeSource());
        // 接入类型
        channelQuery.setAccessMode(channelListQuery.getAccessMode());
        if (Objects.equals(channelListQuery.isExcludeDisabled(), true)) {
            channelQuery.setStatus(GlobalConsts.YES);
        }
        ResponseDTO<List<ChannelSimpleDRO>> listResponseDTO = channelListRemoteService.listByCombinationQuery(channelQuery);
        logger.debug("channelDIO={}, channelListQuery={}", JSON.toJSONString(channelQuery), JSON.toJSONString(listResponseDTO));
        List<ChannelSimpleDRO> channelDROList = listResponseDTO.getData();

        if (Objects.equals(channelListQuery.isExcludeDisabledOrderInput(), true)) {
            // 获取可以后台下单的渠道id
            List<Integer> channelIdList = confOrderChannelBService.listChannelIdByHiddenStatus(GlobalConsts.YES);
            channelDROList = channelDROList.stream()
                    .filter(channelSimpleDRO -> channelIdList.contains(channelSimpleDRO.getChannelId()))
                    .collect(Collectors.toList());
        }

        if (channelDROList == null) {
            return Lists.newArrayList();
        }
        List<KVDict> list = Lists.newArrayListWithCapacity(channelDROList.size());
        channelDROList.forEach((item) ->{
            if(channelListQuery.isFactoryChannel()){
                list.add(KVDict.builder()
                        .value(item.getChannelId())
                        .text(item.getName())
                        .disabled(Objects.equals(item.getStatus(), GlobalConsts.NO))
                        .ext1(String.valueOf(item.getPlat()))
                        .build());
            } else if (!Objects.equals(item.getChannelType(), ChannelTypeEnum.CJ.getCode())) {
                // 排除厂商渠道
                list.add(KVDict.builder()
                        .value(item.getChannelId())
                        .text(item.getName())
                        .disabled(Objects.equals(item.getStatus(), GlobalConsts.NO))
                        .ext1(String.valueOf(item.getPlat()))
                        .build());
            }
        });

        if(channelListQuery.isPermit()){
            SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(super.getLoginStaff(), DpermitConsts.TYPE_COOPERATION_TWO, false);
            if (CollectionUtils.isEmpty(spermitDTO.getItems())) {
                // 没有权限，返回全部
                channelListQuery.setPermit(false);
                return this.getChannelList(channelListQuery);
            }

            // 过滤没有权限的渠道
            Set<Integer> collect = spermitDTO.getItems().stream().collect(Collectors.toSet());
            list.removeIf(e -> !collect.contains(e.getValue()));

            if(CollectionUtils.isEmpty(list)){
                return Lists.newArrayList();
            }
        }

        return list;
    }

    /**
     * 获取全部渠道列表
     *
     * @return
     */
    protected List<KVDict> getAllChannelListByPermit() {
        return this.getAllChannelListByPermit(null, null, GlobalConsts.LEVEL_2, null);
    }

    /**
     * 获取渠道列表
     *
     * @param plat
     * @param keyword
     * @param rank 渠道层级 1一级渠道 2二级渠道
     * @param parentIds 上级渠道id集合
     * @return
     */
    protected List<KVDict> getAllChannelListByPermit(Integer plat, String keyword, Integer rank, List<Integer> parentIds) {
        List<KVDict> list = this.getAllChannelList(plat, keyword, rank, parentIds);
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }

        int channelType = DpermitConsts.TYPE_COOPERATION_TWO;
        if (Objects.equals(rank, GlobalConsts.LEVEL_1)){
            channelType = DpermitConsts.TYPE_COOPERATION_ONE;
        }
        // 权限过滤
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(super.getLoginStaff(), channelType, false);
        if (CollectionUtils.isEmpty(spermitDTO.getItems())) {
            // 没有权限，返回全部
            return list;
        }

        // 过滤没有权限的渠道
        Set<Integer> collect = spermitDTO.getItems().stream().collect(Collectors.toSet());
        list.removeIf(e -> !collect.contains(e.getValue()));
        return list;
    }

    /**
     * 获取渠道列表
     *
     * @param plat 平台
     * @param keyword 关键词
     * @param rank 渠道层级 1一级渠道 2二级渠道
     * @param parentIds 上级渠道id集合
     * @return
     */
    protected List<KVDict> getAllChannelList(Integer plat, String keyword, Integer rank, List<Integer> parentIds) {
        ChannelQuery channelDIO = new ChannelQuery();
        channelDIO.setPlat(plat);
        channelDIO.setKeyword(keyword);
        //channelDIO.setRank(GlobalConsts.LEVEL_2);
        channelDIO.setRank(rank);
        if (CollectionUtil.isNotNullOrEmpty(parentIds)){
            channelDIO.setParentIds(parentIds);
        }
        ResponseDTO<List<ChannelDRO>> channelDRO = channelListRemoteService.listByQuery(channelDIO);
        List<ChannelDRO> channelDROList = channelDRO.getData();
        if (CollectionUtils.isEmpty(channelDROList)) {
            return Lists.newArrayList();
        }
        List<KVDict> list = Lists.newArrayListWithCapacity(channelDROList.size());
        channelDROList.forEach((item) -> {
            list.add(KVDict.builder()
                    .value(item.getChannelId())
                    .text(item.getName())
                    .disabled(Objects.equals(item.getStatus(), GlobalConsts.NO))
                    .ext1(String.valueOf(item.getPlat()))
                    .build());
        });
        return list;
    }

    /**
     * 查询前台服务分类
     *
     * @return
     */
    protected List<KVDict> getShowServCategList() {
        ResponseDTO<List<CategServDRO>> responseDTO = categServListRemoteService.listByQuery(new ForeignCategServQuery());
        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayList();
        }
        List<KVDict> vtList = Lists.newArrayListWithCapacity(responseDTO.getData().size());
        responseDTO.getData().forEach((item) -> {
            vtList.add(KVDict.builder()
                    .value(item.getServCategId())
                    .text(item.getEcServCategName())
                    .disabled(Objects.equals(item.getStatus(), GlobalConsts.NO))
                    .build());
        });
        return vtList;
    }

    /**
     * 查询后台服务分类
     *
     * @return
     */
    protected List<KVDict> getServCategList() {
        ResponseDTO<List<CategServDRO>> responseDTO = categServListRemoteService.listByQuery(new ForeignCategServQuery());
        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayList();
        }
        List<KVDict> vtList = Lists.newArrayListWithCapacity(responseDTO.getData().size());
        responseDTO.getData().forEach((item) -> {
            vtList.add(KVDict.builder()
                    .value(item.getServCategId())
                    .text(item.getServCategName())
                    .disabled(Objects.equals(item.getStatus(), GlobalConsts.NO))
                    .build());
        });
        return vtList;
    }

    /**
     * 查询产品
     * @param queryDTO 产品查询DTO
     * @return
     */
    protected List<KVDict> getServProductList(ProductQueryDTO queryDTO) {
        ProductBaseQuery query = ProductBaseQuery
                .builder()
                .defaultType(1)
                .showType(queryDTO.getShowType())
                .cityId(queryDTO.getCityId())
                .channelId(queryDTO.getChannelId())
                .keyWord(queryDTO.getKeyWord())
                .bizType(queryDTO.getBizType())
                .build();
        if (Objects.nonNull(queryDTO.getCategId())) {
            query.setCategIds(Lists.newArrayList(queryDTO.getCategId()));
        }
        if (Objects.nonNull(queryDTO.getServCategId())) {
            query.setServCategIds(Lists.newArrayList(queryDTO.getServCategId()));
        }
        if (Objects.isNull(queryDTO.getBizType())) {
            query.setBizType(com.zmn.consts.GlobalConsts.BIZ_TYPE_C);
        }
        logger.debug("#getProductList 入参：{}", JSON.toJSONString(query));
        ResponseDTO<List<ProductBaseDRO>> responseDTO = productForeignListRemoteService.listBaseDROByQuery(query);
        logger.debug("#getProductList 出参：{}", JSON.toJSONString(responseDTO));
        if (CollectionUtil.isNullOrEmpty(responseDTO.getData())) {
            return Lists.newArrayList();
        }

        List<KVDict> vtList = Lists.newArrayListWithCapacity(responseDTO.getData().size());
        responseDTO.getData().forEach((item) -> {
            if (!queryDTO.isIncludeDisabled() && Objects.equals(item.getStatus(), GlobalConsts.NO)) {
                return;
            }

            vtList.add(KVDict.builder()
                    .value(item.getProductId())
                    .text(Objects.equals(item.getStatus(), GlobalConsts.NO) ? item.getProductName() + "（禁用）" : item.getProductName())
                    .disabled(false)
                    .pid(item.getServCategId())
                    .ext1(item.getUnit())
                    .ext2(item.getCategId().toString())
                    .build());
        });
        return vtList;
    }

    /**
     * 查询产品
     *
     * @return
     */
    protected List<KVDict> getServProductListByCategId(ProductQueryDTO productQueryDTO) {
        productQueryDTO.setIncludeDisabled(Optional.ofNullable(productQueryDTO.isIncludeDisabled()).orElse(false));

        ProductBaseQuery query = ProductBaseQuery
                .builder()
                .defaultType(1)
                .cityId(productQueryDTO.getCityId())
                .channelId(productQueryDTO.getChannelId())
                .build();
        if (NumberUtil.isNotNullOrZero(productQueryDTO.getServCategId())) {
            query.setServCategIds(Lists.newArrayList(productQueryDTO.getServCategId()));
        }
        if (NumberUtil.isNotNullOrZero(productQueryDTO.getCategId())) {
            query.setCategIds(Lists.newArrayList(productQueryDTO.getCategId()));
        }
        logger.debug("查询产品数据#productForeignListRemoteService.listBaseDROByQuery query={}", query);
        ResponseDTO<List<ProductBaseDRO>> responseDTO = productForeignListRemoteService.listBaseDROByQuery(query);
        logger.debug("查询产品数据#productForeignListRemoteService.listBaseDROByQuery responseDTO={}", responseDTO);
        if (!responseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(responseDTO.getData())) {
            return Lists.newArrayList();
        }
        List<KVDict> vtList = Lists.newArrayListWithCapacity(responseDTO.getData().size() + 1);
        responseDTO.getData().forEach((item) -> {
            if (!productQueryDTO.isIncludeDisabled() && Objects.equals(item.getStatus(), GlobalConsts.NO)) {
                return;
            }

            vtList.add(KVDict.builder()
                    .value(item.getProductId())
                    .text(Objects.equals(item.getStatus(), GlobalConsts.NO) ? item.getProductName() + "（禁用）" : item.getProductName())
                    .disabled(false)
                    .pid(item.getServCategId())
                    .ext1(item.getUnit())
                    .build());
        });
        return vtList;
    }

    /**
     * 增加列表中查询不到产品
     *
     * @return
     */
    protected void appendServProductListById(Integer bizType, Integer productId, List<KVDict> list, Integer showType) {
        if (productId == null || CollectionUtils.isEmpty(list)) {
            return;
        }
        boolean findProduct = list.stream().anyMatch(item -> Objects.equals(productId, item.getValue()));
        if (findProduct) {
            return;
        }
        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setBizType(bizType);
        productDIO.setProductId(productId);
        productDIO.setShowType(showType);
        ResponseDTO<List<ProductBaseDRO>> responseDTO = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        List<ProductBaseDRO> servProductDROS = responseDTO.getData();
        if (CollectionUtil.isNullOrEmpty(servProductDROS)) {
            return;
        }
        ProductBaseDRO productBaseDRO = servProductDROS.get(0);

        list.add(KVDict.builder()
                .value(productBaseDRO.getProductId())
                .text(Objects.equals(productBaseDRO.getStatus(), GlobalConsts.NO) ? productBaseDRO.getProductName() + "（禁用）" : productBaseDRO.getProductName())
                .disabled(false)
                .pid(productBaseDRO.getServCategId())
                .ext1(productBaseDRO.getUnit())
                .build());
    }

    /**
     * 获取产品故障
     *
     * @param productId
     * @return
     */
    public List<KVDict> getSubsidiaryList(int productId) {
        logger.debug("根据产品id查询故障分组#listFaultByProductId productId={}",productId);
        ResponseDTO<List<FaultWarrantyDRO>> responseDTO = productTagsGroupForeignListRemoteService.listFaultByProductId(productId);
        logger.debug("根据产品id查询故障分组#listFaultByProductId responseDTO={}",responseDTO);
        if (!responseDTO.isSuccess() || responseDTO.getData() == null) {
            return Lists.newArrayList();
        }
        List<KVDict> vtList = Lists.newArrayListWithCapacity(responseDTO.getData().size());
        responseDTO.getData().forEach((item) -> {
            if (Objects.equals(item.getStatus(), GlobalConsts.YES)) {
                vtList.add(KVDict.builder()
                        .value(item.getItemId())
                        .text(item.getName())
                        .build());
            }
        });
        return vtList;
    }

    /**
     * 品牌
     *
     * @return
     */
    protected List<KVDict> getBrandList() {
        ResponseDTO<List<BrandDRO>> brandResponseDTO = brandListRemoteService.listAll();
        if (!brandResponseDTO.isSuccess()|| brandResponseDTO.getData() == null) {
            return Lists.newArrayList();
        }
        List<KVDict> vtList = Lists.newArrayListWithCapacity(brandResponseDTO.getData().size());
        brandResponseDTO.getData().forEach((item) -> {
            vtList.add(KVDict.builder()
                    .value(item.getBrandId())
                    .text(item.getName())
                    .disabled(Objects.equals(item.getStatus(), GlobalConsts.NO))
                    .build());
        });
        return vtList;
    }

    /**
     * 获取用户部门ID
     *
     * @return
     */
    protected Integer getDeptId() {
        return super.getLoginStaff().getDeptId();
    }

    protected List<KVDict> option2VKDict(List<Option<Integer>> vtList) {
        if (vtList == null) {
            return Lists.newArrayList();
        }
        List<KVDict> dmList = Lists.newArrayListWithCapacity(vtList.size());
        vtList.forEach((item) -> {
            dmList.add(KVDict.builder()
                    .value(item.getValue())
                    .text(item.getLabel())
                    .disabled(item.getDisabled() == null ? true : item.getDisabled())
                    .build());
        });
        return dmList;
    }

    protected List<KVDict> optionData2VKDict(OptionData vtList) {
        if (vtList == null || CollectionUtil.isNullOrEmpty(vtList.getOptions())) {
            return Lists.newArrayList();
        }
        List<KVDict> dmList = Lists.newArrayListWithCapacity(vtList.getOptions().size());
        List<Option<Integer>> options = vtList.getOptions();
        options.forEach((item) -> {
            dmList.add(KVDict.builder()
                    .value(item.getValue())
                    .text(item.getLabel())
                    .disabled(item.getDisabled() == null ? true : item.getDisabled())
                    .build());
        });
        return dmList;
    }

    protected List<KVDict> vt2VKDict(List<VtDTO> vtList) {
        if (vtList == null) {
            return Lists.newArrayList();
        }
        List<KVDict> dmList = Lists.newArrayListWithCapacity(vtList.size());
        vtList.forEach((item) -> {
            dmList.add(KVDict.builder()
                    .value(item.getValue())
                    .text(item.getText())
                    .disabled(item.getStatus() == null ? true : item.getStatus())
                    .build());
        });
        return dmList;
    }

    protected List<KVDict> dictModel2KVDict(List<DictModel> vtList) {
        if (vtList == null) {
            return Lists.newArrayList();
        }
        List<KVDict> dmList = Lists.newArrayListWithCapacity(vtList.size());
        vtList.forEach((item) -> {
            dmList.add(KVDict.builder()
                    .value(item.getKey())
                    .text(item.getValue())
                    .build());
        });
        return dmList;
    }


    /**
     * 根据渠道类型ID获取渠道列表
     *
     * @param channelTypeId 渠道类型ID
     * @return java.util.List<com.zmn.oms.common.vo.KVDict>
     */
    protected List<KVDict> listChannelByTypeId(Integer channelTypeId) {
        return Collections.emptyList();
    }

    /**
     * 获取登陆用户所属组织架构的子公司id
     * @return
     */
    protected Integer getOrgCompanyId() {
        ResponseDTO<OrganizeDRO> organDROResponseDTO = organizeListRemoteService.getByKey(getLoginStaff().getOrgId());
        OrganizeDRO organDRO = organDROResponseDTO.getData();
        if (Objects.isNull(organDRO)) {
            return 0;
        }
        return organDRO.getCompanyId();
    }

    /**
     * 判断是总部，还是分公司
     *
     * @return true:分公司； false 总公司
     */
    protected boolean isBranchCompany() {
        ResponseDTO<OrganizeDRO> organDROResponseDTO = organizeListRemoteService.getByKey(getLoginStaff().getOrgId());
        OrganizeDRO organDRO = organDROResponseDTO.getData();
        if (organDRO != null) {
            return organDRO.getLevel() == null || organDRO.getLevel() > GlobalConsts.LEVEL_2;
        }
        return true;
    }

    /********************言而有信相关***********************/

    /**
     * 获取厂商可以使用服务类型
     *
     * @param fcProductId
     * @return
     */
    protected List<KVDict> getServCategListByFcProduct(int fcProductId) {
//        ResponseDTO<List<VtDTO>> responseDTO = factoryProductListRemoteService.getServByFcProductId(fcProductId);
        return this.vt2VKDict(null);
    }

    /**
     * 厂商产品 转化 为基础产品
     *
     * @param fcProductId
     * @param servCategId
     * @return
     */
    protected List<KVDict> getPrductIdByFcProduct(int plat, int fcProductId, int servCategId, int channelId) {
        List<KVDict> productList = Lists.newArrayList();

        /*ResponseDTO<List<ServProductDRO>> responseDTO = factoryProductListRemoteService.getByFcProductIdAndServCategIdAndChannelId(fcProductId, servCategId, channelId);
        List<ServProductDRO> servProductDROList = responseDTO.getData();
        if (Objects.isNull(servProductDROList) || servProductDROList.isEmpty()) {
            return productList;
        }
        responseDTO.getData().forEach(productDRO -> {
            // 过滤平台
            if (!NumberUtil.isNullOrZero(plat) && StringUtils.isNotBlank(productDRO.getShowPlat()) && !productDRO.getShowPlat().contains(String.valueOf(plat))) {
                return;
            }

            if (Objects.equals(productDRO.getStatus(), GlobalConsts.NO)) {
                return ;
            }
            productList.add(KVDict.builder()
                    .value(productDRO.getProductId())
                    .text(productDRO.getName())
                    .build());
        });*/
        return productList;
    }

    /**
     * 获取产品故障
     *
     * @param productId
     * @return
     */
    protected List<KVDict> getFactorySubsidiaryList(int productId) {
        return this.getSubsidiaryList(productId);
    }

    /**
     * 获取厂商列表
     *
     * @param factoryId
     * @return
     */
    protected List<KVDict> getFactoryListById(Integer factoryId) {
        return Lists.newArrayList();
        /*ResponseDTO<FactoryDRO> responseDTO = factoryListRemoteService.getFactoryById(factoryId);
        FactoryDRO factoryDRO = responseDTO.getData();
        if(Objects.isNull(factoryDRO)){
            return Lists.newArrayList();
        }

        List<KVDict> factoryList = Lists.newArrayListWithCapacity(1);

        factoryList.add(KVDict.builder()
                .value(factoryDRO.getFactoryId())
                .text(factoryDRO.getCompanyName())
                .build());

        return factoryList;*/
    }

    /**
     * 获取厂商列表
     *
     * @param onlyCanInput
     * @return
     */
    protected List<KVDict> getFactoryListByDept(Boolean onlyCanInput) {
        return Lists.newArrayList();
        /*FactoryQueryDIO factoryQueryDIO = new FactoryQueryDIO();
        if(onlyCanInput != null){
            factoryQueryDIO.setCanCreateOrder(onlyCanInput ? GlobalConsts.YES : GlobalConsts.NO);
        }
        ResponseDTO<List<FactoryDRO>> responseDTO = factoryListRemoteService.listByQuery(factoryQueryDIO);

        List<FactoryDRO> droList = responseDTO.getData();
        if (CollectionUtils.isEmpty(droList)) {
            return Lists.newArrayList();
        }

        // 移除禁用的厂商
        droList.removeIf(dro -> {return Objects.equals(dro.getStatus(), GlobalConsts.NO);});

        // 获取渠道权限
        SpermitDTO<Integer> spermitDTO = staffPermitRemoteService.listDpermitByLoginStaff(super.getLoginStaff(), DpermitConsts.TYPE_CHANNEL_C2, false);
        if (CollectionUtils.isEmpty(spermitDTO.getItems())) {
            // 没有权限，返回全部
            List<KVDict> factoryList = Lists.newArrayListWithCapacity(droList.size());
            droList.forEach((item) -> {
                factoryList.add(KVDict.builder()
                        .value(item.getFactoryId())
                        .text(item.getCompanyName())
                        .build());
            });
            return factoryList;
        }

        // 权限过滤
        Set<Integer> collect = spermitDTO.getItems().stream().collect(Collectors.toSet());
        List<KVDict> factoryList = Lists.newArrayListWithCapacity(droList.size());
        droList.forEach((item) -> {
            if(collect.contains(item.getChannelId())){
                factoryList.add(KVDict.builder()
                        .value(item.getFactoryId())
                        .text(item.getCompanyName())
                        .build());
            }
        });
        return factoryList;*/
    }

    /**
     * 获取服务商列表
     *
     * @return
     */
    protected List<KVDict> getServiceProviderList() {
        ResponseDTO<List<VtDTO>> responseDTO = spManageListRemoteService.listAllServProviderVt();
        List<VtDTO> spServProviderSimpleDROList = responseDTO.getData();
        if (CollectionUtils.isEmpty(spServProviderSimpleDROList)) {
            return Lists.newArrayList();
        }
        List<KVDict> result = BeanMapper.mapList(spServProviderSimpleDROList, KVDict.class);
        return result;
    }

    /**
     * 上传图片
     * @param file 文件
     * @param path 路径
     * @return
     */
    protected ResultDTO uploaderImage(MultipartFile file, String path) {
        String imgUrl;
        try {
            imgUrl = orderWorkUploadService.uploaderImage(file, path);
        } catch (FileUploadException e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail("图片上传失败");
        }
        ResultDTO resultSuccess = ResultDTO.success(imgUrl, "图片上传成功");
        return resultSuccess;
    }

    /**
     * 上传文件
     *
     * @param file 文件
     * @param path 路径
     * @return
     */
    protected ResultDTO uploaderFile(MultipartFile file, String path) {
        String fileUrl;
        try {
            fileUrl = orderWorkUploadService.uploaderFile(file, path);
        } catch (FileUploadException e) {
            logger.error(e.getMessage(), e);
            return ResultDTO.fail("文件上传失败");
        }
        ResultDTO resultSuccess = ResultDTO.success(fileUrl, "文件上传成功");
        return resultSuccess;
    }

    /**
     * 获取店铺列表
     * @param plat
     * @param shopType
     * @param sourceCompanyId
     * @param name
     * @return
     */
    protected List<KVDict<Integer>> getShopList(Integer plat, Integer shopType,Integer sourceCompanyId, String name) {
        List<KVDict<Integer>> shopList = Lists.newArrayList();

        ShopTypeDIO dio = new ShopTypeDIO();
        if (!NumberUtil.isNullOrZero(plat)) {
            dio.setPlatIds(Lists.newArrayList(plat));
        }
        if (!NumberUtil.isNullOrZero(sourceCompanyId)){
            dio.setSpIds(Lists.newArrayList(sourceCompanyId));
        }
        dio.setType(shopType);
        dio.setShopName(name);
        dio.setStatus(2);
        com.zmn.common.dto.ResponseDTO<ShopDRO> responseDTO = shopRemoteService.listShopByType(dio);
        if (CollectionUtils.isNotEmpty(responseDTO.getItems())) {
            responseDTO.getItems().forEach(shopDRO -> {
                shopList.add(KVDict.<Integer>builder()
                        .value(shopDRO.getShopId())
                        .text(shopDRO.getShopName())
                        .build());
            });
        }
        return shopList;
    }

    /**
     * 获取前端产品
     * @param productId
     * @return
     */
    protected ShowProductDTO getShowProductIdByProductId(Integer productId) {
        if (NumberUtil.isNullOrZero(productId)) {
            return null;
        }

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productRemote = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        logger.debug("#获取产品接口productListRemoteService#listBaseDROByDIO#入参[{}],出参[{}]", productDIO, productRemote);
        List<ProductBaseDRO> servProductDROS = productRemote.getData();
        if (CollectionUtil.isNullOrEmpty(servProductDROS)) {
            logger.error("[{}]产品不存在", productId);
            return null;
        }

        ProductBaseDRO productBaseDRO = servProductDROS.get(0);
        ShowProductDTO dto = new ShowProductDTO();
        if (Objects.equals(productBaseDRO.getShowType(), BaseProductConsts.EC_SHOW_TYPE)) {
            dto.setShowProductId(productBaseDRO.getProductId());
            dto.setShowProductName(productBaseDRO.getProductName());
            dto.setShowCategId(productBaseDRO.getCategId());
            dto.setShowCategName(productBaseDRO.getCategName());
            dto.setShowCategOneId(productBaseDRO.getCategOneId());
            dto.setShowCategOneName(productBaseDRO.getCategOneName());
            dto.setServCategId(productBaseDRO.getServCategId());
            dto.setServCategName(productBaseDRO.getServCategName());
        } else {
            // 后端产品找前端产品
            DefaultEcProductQuery defaultEcProductQuery = new DefaultEcProductQuery();
            defaultEcProductQuery.setProductIdList(Lists.newArrayList(productBaseDRO.getProductId()));
            defaultEcProductQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
            com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> showProductRemote = productForeignListRemoteService.listEcErpProductByQuery(defaultEcProductQuery);
            if (!CollectionUtils.isEmpty(showProductRemote.getData())) {
                // 前台产品信息
                dto.setShowProductId(showProductRemote.getData().get(0).getProductId());
                dto.setShowProductName(showProductRemote.getData().get(0).getProductName());
                dto.setShowCategId(showProductRemote.getData().get(0).getCategId());
                dto.setShowCategName(showProductRemote.getData().get(0).getCategName());
                dto.setShowCategOneId(showProductRemote.getData().get(0).getCategOneId());
                dto.setShowCategOneName(showProductRemote.getData().get(0).getCategOneName());
                dto.setServCategId(showProductRemote.getData().get(0).getServCategId());
                dto.setServCategName(showProductRemote.getData().get(0).getServCategName());

                // 后台产品信息
                dto.setProductId(productBaseDRO.getProductId());
                dto.setProductName(productBaseDRO.getProductName());
                dto.setCategId(productBaseDRO.getCategId());
                dto.setCategName(productBaseDRO.getCategName());
                dto.setCategOneId(productBaseDRO.getCategOneId());
                dto.setCategOneName(productBaseDRO.getCategOneName());
            } else {
                logger.error("后端产品[{}]未找到前端产品", productId);
                return null;
            }
        }
        return dto;
    }

    /**
     * 获取前端产品
     * @param productId
     * @return
     */
    protected ProductBO getShowProductByProductId(Integer productId) {
        if (NumberUtil.isNullOrZero(productId)) {
            return null;
        }

        ProductBO bo = new ProductBO();

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productRemote = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        logger.debug("#获取产品接口productListRemoteService#listBaseDROByDIO#入参[{}],出参[{}]", productDIO, productRemote);
        List<ProductBaseDRO> servProductDROS = productRemote.getData();
        if (CollectionUtil.isNullOrEmpty(servProductDROS)) {
            logger.error("[{}]产品不存在", productId);
            return null;
        }

        ProductBaseDRO productBaseDRO = servProductDROS.get(0);
        if (Objects.equals(productBaseDRO.getShowType(), BaseProductConsts.EC_SHOW_TYPE)) {
            bo = BeanMapper.map(productBaseDRO, ProductBO.class);
            bo.setProductGroupId(productBaseDRO.getFicoCategId());
            bo.setProductGroupName(productBaseDRO.getFicoCategName());

        } else {
            // 后端产品找前端产品
            DefaultEcProductQuery defaultEcProductQuery = new DefaultEcProductQuery();
            defaultEcProductQuery.setProductIdList(Lists.newArrayList(productBaseDRO.getProductId()));
            defaultEcProductQuery.setShowType(BaseProductConsts.EC_SHOW_TYPE);
            com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> showProductRemote = productForeignListRemoteService.listEcErpProductByQuery(defaultEcProductQuery);
            if (!CollectionUtils.isEmpty(showProductRemote.getData())) {
                bo = BeanMapper.map(showProductRemote.getData().get(0), ProductBO.class);
                bo.setProductGroupId(productBaseDRO.getFicoCategId());
                bo.setProductGroupName(productBaseDRO.getFicoCategName());
            } else {
                logger.error("后端产品[{}]未找到前端产品", productId);
            }
        }
        return bo;
    }

    /**
     * 获取后端产品
     * @param productId
     * @return
     */
    protected ProductBO getProductByProductId(Integer productId) {
        if (NumberUtil.isNullOrZero(productId)) {
            return null;
        }

        ProductBO bo = new ProductBO();

        ProductBaseQuery productDIO = new ProductBaseQuery();
        productDIO.setProductId(productId);
        com.zmn.common.dto2.ResponseDTO<List<ProductBaseDRO>> productRemote = productForeignListRemoteService.listBaseDROByQuery(productDIO);
        logger.debug("#获取产品接口productListRemoteService#listBaseDROByDIO#入参[{}],出参[{}]", productDIO, productRemote);
        List<ProductBaseDRO> servProductDROS = productRemote.getData();
        if (CollectionUtil.isNullOrEmpty(servProductDROS)) {
            logger.error("[{}]产品不存在", productId);
            return null;
        }

        ProductBaseDRO productBaseDRO = servProductDROS.get(0);
        if (Objects.equals(productBaseDRO.getShowType(), BaseProductConsts.ERP_SHOW_TYPE)) {
            bo = BeanMapper.map(productBaseDRO, ProductBO.class);
            bo.setProductGroupId(productBaseDRO.getFicoCategId());
            bo.setProductGroupName(productBaseDRO.getFicoCategName());
        }
        return bo;
    }

    /**
     * 查询回访类别
     * @param
     * @return
     */
    protected List<KVDict<Integer>> getVisitCategList() {
        ReplyCategoryQuery replyCategoryQuery = new ReplyCategoryQuery();
        replyCategoryQuery.setStatus(GlobalConsts.YES);
        List<ReplyCategory> replyCategoryList = replyCategoryService.listByQuery(replyCategoryQuery);

        List<KVDict<Integer>> items = Lists.newArrayList();
        replyCategoryList.forEach(item -> {
            items.add(KVDict.<Integer>builder()
                    .value(item.getCategId())
                    .text(item.getName())
                    .build());
        });
        return items;
    }


    protected List<KVDict> getServCategByChannelIdAndShowTypeAndCityId(Integer channelId, @Nullable Integer showType, Integer cityId) {
        List<KVDict> servCategList = Lists.newArrayList();
        if(NumberUtil.isNullOrZero(channelId) || NumberUtil.isNullOrZero(cityId)) {
            return servCategList;
        }
        if (NumberUtil.isNullOrZero(showType)) {
            showType = BaseProductConsts.ERP_SHOW_TYPE;
        }

        logger.debug("根据渠道、城市、产品类型获取服务分类 入参：channelId:{}, showType:{}, cityId:{}", channelId, showType, cityId);
        com.zmn.common.dto2.ResponseDTO<List<CategServDRO>> responseDTO = channelAreaCategListRemoteService.listAreaCategByChannelIdAndCityId(channelId, cityId);
        logger.debug("根据渠道、城市、产品类型获取服务分类 出参：{}", JSON.toJSONString(responseDTO));

        if (responseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(responseDTO.getData())) {
            responseDTO.getData().forEach((item) -> {
                servCategList.add(KVDict.<Integer>builder()
                        .value(item.getServCategId())
                        .text(item.getServCategName())
                        .build());
            });
        }

        return servCategList;
    }

    protected LoginStaff getCurrentStaff(){
        return super.getLoginStaff();
    }

    protected Map<String, String> listExpressCompany() {
        Map<String, String> companys = Maps.newHashMap();

        ResponseDTO<List<ExpressageCompany>> responseDTO = expressageRemoteService.listCompany();
        if (responseDTO.isSuccess() && CollectionUtil.isNotNullOrEmpty(responseDTO.getData())) {
            responseDTO.getData().forEach((item) -> {
                if (!item.getName().contains("订单")) {
                    companys.put(item.getCode(), item.getName());
                }
            });
        }

        return companys;
    }
}
